#ifndef __WIZ_DATATYPE_MEMFUNC_TEMPLATE_HPP__SHANHAOBO_19800429__
#define __WIZ_DATATYPE_MEMFUNC_TEMPLATE_HPP__SHANHAOBO_19800429__

#include "../../Base/WizBase.hpp"

namespace Wiz
{
    namespace MemFunc
    {
        namespace Storage
        {
            struct Type
            {
                Type() : m_InstPtr(WIZ_NULLPTR), m_MemFPtr(WIZ_NULLPTR)
                {
                }
                Type(::Wiz::Void::Ptr InstPtr, ::Wiz::Void::Ptr MemFPtr) : m_InstPtr(InstPtr), m_MemFPtr(MemFPtr)
                {
                }
                ::Wiz::Void::Ptr m_InstPtr;
                ::Wiz::Void::Ptr m_MemFPtr;
            };
            WIZ_DECLARE(::Wiz::MemFunc::Storage::Type);
        } /// end of namespace Storage

        template <class ClassT, class ParamT> class Type;
    } /// end of namespace MemFunc
} /// end of namespace Wiz

#endif /*__WIZ_DATATYPE_MEMFUNC_TEMPLATE_HPP__SHANHAOBO_19800429__*/

//////////////////////////////////////////////////////////////////////////

#if defined(WIZ_MEMFUNC_PARAM_COUNT) && (WIZ_MEMFUNC_PARAM_COUNT >= 0) && (WIZ_MEMFUNC_PARAM_COUNT < 255)

namespace Wiz
{
    namespace MemFunc
    {
        template<class ClassT, class RetT WIZ_COMMA_IF(WIZ_MEMFUNC_PARAM_COUNT) WIZ_ENUM_PARAM_X(WIZ_MEMFUNC_PARAM_COUNT, class T)>
        class Type<ClassT, RetT(WIZ_ENUM_PARAM_X(WIZ_MEMFUNC_PARAM_COUNT, T))>
        {
            typedef ClassT              tClass;
            typedef RetT                tRet;
            typedef tRet(tClass::*tMemberFPtr)(WIZ_ENUM_PARAM_X(WIZ_MEMFUNC_PARAM_COUNT, T));
            typedef tRet(tClass::*tMemberConstFPtr)(WIZ_ENUM_PARAM_X(WIZ_MEMFUNC_PARAM_COUNT, T)) const;
            typedef tMemberFPtr         tMemberPtr;
            typedef tMemberConstFPtr    tMemberConstPtr;
        public:
            Type() : m_Storage()
            {
                WIZ_STATIC_ASSERT(sizeof(m_Storage.m_InstPtr) == sizeof(m_ClassPtr));
                WIZ_STATIC_ASSERT(sizeof(m_Storage.m_MemFPtr) == sizeof(m_MemberPtr));
            }
            Type(::Wiz::Void::Ptr ClassPtr, ::Wiz::Void::Ptr MemPtr)
            {
                WIZ_STATIC_ASSERT(sizeof(m_Storage.m_InstPtr) == sizeof(m_ClassPtr));
                WIZ_STATIC_ASSERT(sizeof(m_Storage.m_MemFPtr) == sizeof(m_MemberPtr));
                /// Don't initialize union members;
                m_Storage.m_InstPtr = ClassPtr;
                m_Storage.m_MemFPtr = MemPtr;
            }
            Type(const tClass* ClassPtr, tMemberPtr MemberPtr)
            {
                WIZ_STATIC_ASSERT(sizeof(m_Storage.m_InstPtr) == sizeof(m_ClassPtr));
                WIZ_STATIC_ASSERT(sizeof(m_Storage.m_MemFPtr) == sizeof(m_MemberPtr));
                /// Don't initialize union members;
                m_ClassPtr = ::Wiz::Cast::Const<tClass*>(ClassPtr);
                m_MemberPtr = MemberPtr;
            }
            Type(const tClass* ClassPtr, tMemberConstPtr MemberPtr)
            {
                WIZ_STATIC_ASSERT(sizeof(m_Storage.m_InstPtr) == sizeof(m_ClassPtr));
                WIZ_STATIC_ASSERT(sizeof(m_Storage.m_MemFPtr) == sizeof(m_MemberPtr));
                /// Don't initialize union members;
                m_ClassPtr = ::Wiz::Cast::Const<tClass*>(ClassPtr);
                m_MemberConstPtr = MemberPtr;
            }
            Type(::Wiz::MemFunc::Storage::In ST)
            {
                m_Storage = ST;
            }
        public:
            tRet operator()(WIZ_ENUM_PARAM_XY(WIZ_MEMFUNC_PARAM_COUNT, T, A))
            {
                return (m_ClassPtr->*m_MemberPtr)(WIZ_ENUM_PARAM_X(WIZ_MEMFUNC_PARAM_COUNT, A));
            }
            tRet operator()(WIZ_ENUM_PARAM_XY(WIZ_MEMFUNC_PARAM_COUNT, T, A)) const
            {
                return (m_ClassPtr->*m_MemberConstPtr)(WIZ_ENUM_PARAM_X(WIZ_MEMFUNC_PARAM_COUNT, A));
            }
        public:
            ::Wiz::Void::Type Set(const tClass* ClassPtr, tMemberPtr MemberPtr)
            {
                m_ClassPtr = ::Wiz::Cast::Const<tClass*>(ClassPtr);;
                m_MemberPtr = MemberPtr;
            }
            ::Wiz::Void::Type Set(const tClass* ClassPtr, tMemberConstPtr MemberPtr)
            {
                m_ClassPtr = ::Wiz::Cast::Const<tClass*>(ClassPtr);;
                m_MemberConstPtr = MemberPtr;
            }
            ::Wiz::Void::Type SaveTo(::Wiz::MemFunc::Storage::Out ST)
            {
                ST = m_Storage;
            }
        protected:
            union
            {
                struct
                {
                    ::Wiz::MemFunc::Storage::Type m_Storage;
                };
                struct
                {
                    tClass*                 m_ClassPtr;
                    union
                    {
                        tMemberPtr          m_MemberPtr;
                        tMemberConstPtr     m_MemberConstPtr;
                    };
                };
            };
        };
    } /// end of namespace MemFunc
} /// end of namespace Wiz

#endif /*WIZ_MEMFUNC_PARAM_COUNT*/
